#include "laurin-80211-access-point.h"


Laurin80211AccessPoint::Laurin80211AccessPoint(u_int8_t* mac, LaurinBeaconDetails beacon): Laurin80211Station(mac, mac)
{
	_details = beacon;
	_distance_from_monitor = -1;
	_distance_from_ap = -1;
	_distance_monitor_ap = -1;
	_beacon_elaborated = false;
}


Laurin80211AccessPoint::Laurin80211AccessPoint(const Laurin80211AccessPoint& accessPoint) : Laurin80211Station(accessPoint)
{
	_details = accessPoint._details;
	_distance_from_monitor = accessPoint._distance_from_monitor;
	_distance_from_ap = accessPoint._distance_from_ap;
	_distance_monitor_ap = accessPoint._distance_monitor_ap;
	_beacon_elaborated = accessPoint._beacon_elaborated;
}


Laurin80211AccessPoint::~Laurin80211AccessPoint()
{
	_beacons.clear();
}


LaurinBeaconDetails Laurin80211AccessPoint::getBeaconDetails() const
{
	return _details;
}


bool Laurin80211AccessPoint::isLocationAvaible()
{
	if(!_beacon_elaborated)
		return elaborateBeaconTSFT();

	return _distance_from_monitor > 0;
}


void Laurin80211AccessPoint::setDistanceFromMonitor(double distance)
{
	_distance_from_monitor = distance;
	_distance_from_ap = 0;
	_distance_monitor_ap = distance;
}


void Laurin80211AccessPoint::addBeaconTSFT(u_int64_t beacon_time)
{
	_beacons.push_front(beacon_time);
}


bool Laurin80211AccessPoint::elaborateBeaconTSFT()
{
	if(_beacons.size() <= 1)
		return false;

	_beacon_elaborated = false;
	_beacons.sort();

	std::list<u_int64_t>::iterator b = _beacons.begin();
	std::list<u_int64_t>::iterator e = _beacons.end();
	std::list<u_int64_t>::iterator s = _beacons.begin();
	s++;

	int count1 = 0;
	int count2 = 0;

	while(s != e)
	{
		int tmp = *s - *b - _details.Interval;


		if(tmp == 0)
			count1++;

		else if(tmp == 1)
			count2++;

		s++;
		b++;
	}

	_beacon_elaborated = true;

	if(count2 == 0 || count1 + count2 == 0)
		return false;


	double tof = (double) ((count2 * 0.5) / ((double) count1 + count2));
	_distance_from_monitor = tof * SPEED_OF_LIGHT;
	_distance_monitor_ap = tof * SPEED_OF_LIGHT;
	_distance_from_ap = 0;
	return true;
}
